package com.xs.langchain4j_springboot.config;

import com.xs.langchain4j_springboot.service.ToolsService;

import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.service.*;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import dev.langchain4j.store.embedding.redis.RedisEmbeddingStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AiConfig {

    public interface Assistant {

        @SystemMessage("""
                你是一个翻译专家,请你将{{chineseName}}翻译成英文，你必须仔细查询知识库来判断你翻译后的英文名是否重名，即只要单词的构造完全相同，不管什么意义都属于重名，并不需要调用任何tools，如果有重名你必须重新翻译一个，坚决不能出现与知识库中相同的英文，可以简单加个后缀区分不同英文就可以，这个后缀必须是英文字母或者单词，记住你不需要考虑其他因素，加个标识区分一下就可以，果断一点。”
                """)
        String chat(@UserMessage String chineseName);
        // 流式响应

        @SystemMessage("""
                你是一个翻译专家,请你将{{chineseName}}翻译成英文，你必须仔细查询知识库来判断你翻译后的英文名是否重名，即只要单词的构造完全相同，不管什么意义都属于重名，并不需要调用任何tools，如果有重名你必须重新翻译一个，坚决不能出现与知识库中相同的英文，可以简单加个后缀区分不同英文就可以，这个后缀必须是英文字母或者单词，记住你不需要考虑其他因素，加个标识区分一下就可以，果断一点”
                """)
        TokenStream stream(String chineseName);


        @SystemMessage("""
                您是由“刘文锋”研发的AI助手。请以友好、乐于助人且愉快的方式来回复。
                您正在通过在线聊天系统与客户互动。
                请你尽自己最大的能力准确匹配外部工具和向量知识库中的内容，
                对于与用户问题无关的内容不需要返回给用户。
                请讲中文。
                切记：你开头的第一句话必须是“曼巴 out！”
                今天的日期是 {{current_date}}。
                """)
        TokenStream streamWithTwoParams(@UserMessage String message,@V("current_date") String currentDate);

    }

/*    @Bean
   public QwenEmbeddingModel qwenEmbeddingModel(){
        return  QwenEmbeddingModel.builder()
                .apiKey("sk-8675e9b7aae54b70ba0399a37d8ca0a1")
                .modelName("text-embedding-v1")
                .build();
    }*/




    @Bean
    public EmbeddingStore embeddingStore() {
        return RedisEmbeddingStore.builder()
                .host("127.0.0.1")
                .port(6380)
                .indexName("embedding")
                .dimension(1024)
                .build();
    }

    @Bean
    public Assistant assistant(ChatLanguageModel qwenChatModel,
                               StreamingChatLanguageModel qwenStreamingChatModel,
                               ToolsService toolsService,
                               EmbeddingStore embeddingStore,
                               EmbeddingModel embeddingModel
    ) {
        // 对话记忆
        ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);

        // 内容检索器
        ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder()
                .embeddingStore(embeddingStore)
                .embeddingModel(embeddingModel)
                .maxResults(5) // 最相似的5个结果
                .minScore(0.6) // 只找相似度在0.6以上的内容
                .build();

        // 为Assistant动态代理对象  chat  --->  对话内容存储ChatMemory----> 聊天记录ChatMemory取出来 ---->放入到当前对话中
        Assistant assistant = AiServices.builder(Assistant.class)
                .tools(toolsService)
                .contentRetriever(contentRetriever)
                .chatLanguageModel(qwenChatModel)
                .streamingChatLanguageModel(qwenStreamingChatModel)
                .chatMemory(chatMemory)
                .build();

        return  assistant;
    }



    public interface AssistantUnique {

        String chat(@MemoryId int memoryId, @UserMessage String userMessage);
        // 流式响应
        TokenStream stream(@MemoryId int memoryId, @UserMessage String userMessage);
    }

    @Bean
    public AssistantUnique assistantUnique(ChatLanguageModel qwenChatModel,
                                           StreamingChatLanguageModel qwenStreamingChatModel) {

        AssistantUnique assistant = AiServices.builder(AssistantUnique.class)
                .chatLanguageModel(qwenChatModel)
                .streamingChatLanguageModel(qwenStreamingChatModel)
                .chatMemoryProvider(memoryId ->
                        MessageWindowChatMemory.builder().maxMessages(10)
                                .id(memoryId).build()
                )
                .build();

        return assistant;
    }





    @Bean
    public AssistantUnique assistantUniqueStore(ChatLanguageModel qwenChatModel,
                                                StreamingChatLanguageModel qwenStreamingChatModel) {

        PersistentChatMemoryStore store = new PersistentChatMemoryStore();

        ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory.builder()
                .id(memoryId)
                .maxMessages(10)
                .chatMemoryStore(store)
                .build();

        AssistantUnique assistant = AiServices.builder(AssistantUnique.class)
                .chatLanguageModel(qwenChatModel)
                .streamingChatLanguageModel(qwenStreamingChatModel)
                .chatMemoryProvider(chatMemoryProvider)
                .build();
        return assistant;
    }
}
